export class PerformanceTimer {
  private startTime?: [number, number];
  private endTime?: [number, number];
  private isRunning = false;

  /**
   * 开始计时
   */
  start(): void {
    if (this.isRunning) {
      throw new Error('Timer is already running');
    }
    this.startTime = process.hrtime();
    this.isRunning = true;
  }

  /**
   * 结束计时
   */
  end(): void {
    if (!this.isRunning) {
      throw new Error('Timer is not running');
    }
    this.endTime = process.hrtime(this.startTime);
    this.isRunning = false;
  }

  /**
   * 获取耗时（毫秒）
   */
  get milliseconds(): number {
    if (!this.endTime) {
      throw new Error('Timer has not ended');
    }
    return this.endTime[0] * 1000 + this.endTime[1] / 1000000;
  }

  /**
   * 获取耗时（纳秒）
   */
  get nanoseconds(): number {
    if (!this.endTime) {
      throw new Error('Timer has not ended');
    }
    return this.endTime[0] * 1e9 + this.endTime[1];
  }

  /**
   * 获取耗时（秒）
   */
  get seconds(): number {
    if (!this.endTime) {
      throw new Error('Timer has not ended');
    }
    return this.endTime[0] + this.endTime[1] / 1e9;
  }

  /**
   * 获取格式化后的耗时字符串
   */
  toString(): string {
    if (!this.endTime) {
      throw new Error('Timer has not ended');
    }
    return `${this.milliseconds.toFixed(3)}ms`;
  }

  /**
   * 自动计时异步函数的执行
   * @param fn 要计时的异步函数
   * @returns 包含执行结果和耗时的Promise
   */
  static async time<T>(
    fn: () => Promise<T>,
  ): Promise<{ result: T; duration: number }> {
    const timer = new PerformanceTimer();
    timer.start();

    try {
      const result = await fn();
      timer.end();

      return {
        result,
        duration: timer.milliseconds,
      };
    } catch (error) {
      timer.end();
      throw error;
    }
  }
}

/* 等待一个计时器完成 Promise*/
export function awaitTime(ms: number) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

interface ScheduleOptions {
  /** 开始时间（默认立即开始） */
  startTime?: Date;
  /** 结束时间（与持续时间二选一） */
  endTime?: Date;
  /** 持续时间（毫秒，从开始时间计算） */
  duration?: number;
  /** 主动关闭任务 */
  cancel?: () => boolean;
  /** 成功回调 */
  // @typescript-eslint/no-unsafe-function-type
  // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type
  success?: Function;
}

/**
 * 在指定时间段内不间断执行异步任务
 * @param task 要执行的异步任务
 * @param options 调度配置选项
 */
export async function executeContinuously(
  task: () => Promise<any>,
  options: ScheduleOptions,
): Promise<void> {
  // 参数校验
  if (!options.endTime && typeof options.duration === 'undefined') {
    throw new Error('必须提供 endTime 或 duration 参数');
  }

  // 计算时间范围
  const startTimestamp = options.startTime?.getTime() ?? Date.now();
  const endTimestamp = options.endTime
    ? options.endTime.getTime()
    : startTimestamp + (options.duration || 0);

  if (endTimestamp <= startTimestamp) {
    throw new Error('结束时间必须晚于开始时间');
  }

  // 等待初始延迟
  const initialDelay = startTimestamp - Date.now();
  if (initialDelay > 0) {
    await new Promise((resolve) => setTimeout(resolve, initialDelay));
  }
  const cancel = options.cancel || (() => false);

  // 持续执行循环
  while (Date.now() < endTimestamp && !cancel()) {
    try {
      // 执行任务并等待完成
      await task();
    } catch (error) {
      console.error('[任务执行失败]', error);
    }

    // 每次执行后检查是否超时
    if (Date.now() >= endTimestamp) break;
  }
  const success = options.success || (() => 1);
  // eslint-disable-next-line @typescript-eslint/no-unsafe-call
  success();
}
export function hoursToTime(time: string) {
  const curTime = new Date();
  const t = time.split(',').map(Number) as [number, number, number, number];
  curTime.setHours(...t);
  return curTime;
}

export function hasStringTime(time: string) {
  return /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[12]\d|3[01]) (0\d|1\d|2[0-3]):([0-5]\d):([0-5]\d)$/.test(
    time,
  );
}

export function stringToTime(time: string) {
  return hasStringTime(time) ? new Date(time) : hoursToTime(time);
}
